package com.runner.track;

import java.io.BufferedReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.StringTokenizer;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.math.Vector2;
import com.runner.track.design.TrackDesign;
import com.runner.utility.Constants;
import com.runner.utility.Locator;

public class Track implements Constants {

	private ArrayList<Block> blocks;
	private ArrayList<Block> removedBlocks;
	private ArrayList<Coin> coins;
	private ArrayList<Coin> removedCoins;
	private Ground ground;
	private Goal goal;
	private BufferedReader br;

	public Track(String path) {
		blocks = new ArrayList<Block>();
		removedBlocks = new ArrayList<Block>();
		removedCoins = new ArrayList<Coin>();
		coins = new ArrayList<Coin>();
		ground = new Ground();
		br = new BufferedReader(Gdx.files.internal(path).reader());
		readTrack();
	}

	public void loadCoins(ArrayList<Coin> coins) {
		this.coins.addAll(coins);
	}

	public void render(SpriteBatch sb) {
		for (Block b : blocks) {
			b.render(sb);
		}
		ground.render(sb);
		if (goal != null) {
			goal.render(sb);
		}
		for (Coin c : coins) {
			c.render(sb);
		}
	}

	public void update(float delta) {
		// update blocks
		for (Block b : blocks) {
			b.update(delta);
			if (!b.isExists()) {
				removedBlocks.add(b);
			}
		}
		blocks.removeAll(removedBlocks);
		removedBlocks.clear();

		// update coins
		for (Coin c : coins) {
			c.update(delta);
			if (!c.isExists()) {
				removedCoins.add(c);
			}
		}
		coins.removeAll(removedCoins);
		removedCoins.clear();

		// update ground
		ground.update(delta);
		if (goal != null) {
			goal.update(delta);
		}

		/*lastDistance += -Block.SPEED * Locator.getXGameSpeed() * delta;
		System.out.println(", last dist " + lastDistance);
		if (!endOfFile) {
			readTrack();
		}*/

	}

	public void delete() {
		for (Block b : blocks) {
			b.delete();
		}
		blocks.clear();
		for (Coin c : coins) {
			c.delete();
		}
		coins.clear();
		goal.delete();
		ground.delete();
	}

	public ArrayList<Coin> getCoins() {
		return coins;
	}

	private void readTrack() {
		String info = null;
		try {
			StringTokenizer st = null;
			float distance = 0;
			int count=0;
			while ((info = br.readLine()) != null) {
				st = new StringTokenizer(info);
				if (st.hasMoreTokens()) { // x position of block is that much
											// more distance from last block
					distance += Float.valueOf(st.nextToken()) * BLOCK_WIDTH * Locator.getxSpriteScale();
					while (st.hasMoreTokens()) { // block y position
						float height = Float.valueOf(st.nextToken());
						switch (st.nextToken()) {
						case "n":
							blocks.add(new NormalBlock(new Vector2(distance, (GROUND_HEIGHT * Locator.getySpriteScale()) + height * BLOCK_HEIGHT
									* Locator.getySpriteScale())));
							break;
						case "u":
							blocks.add(new MovingBlock(new Vector2(distance, (GROUND_HEIGHT * Locator.getySpriteScale()) + height * BLOCK_HEIGHT
									* Locator.getySpriteScale()),true));
							break;
						case "d":
							blocks.add(new MovingBlock(new Vector2(distance, (GROUND_HEIGHT * Locator.getySpriteScale()) + height * BLOCK_HEIGHT
									* Locator.getySpriteScale()),false));
							break;
						case "e":
							goal = new Goal(new Vector2(distance, 0));
							break;
						case "ca":
							count = Integer.valueOf(st.nextToken());
							coins.addAll(TrackDesign.addArc(distance, (GROUND_HEIGHT * Locator.getySpriteScale()) + height * BLOCK_HEIGHT
									* Locator.getySpriteScale(), count));
							break;
						case "cl":
							count = Integer.valueOf(st.nextToken());
							coins.addAll(TrackDesign.addCoinLine(distance, (GROUND_HEIGHT * Locator.getySpriteScale()) + height * BLOCK_HEIGHT
									* Locator.getySpriteScale(), count));
							break;
						case "ha":
							count = Integer.valueOf(st.nextToken());
							coins.addAll(TrackDesign.addHalfArc(distance, (GROUND_HEIGHT * Locator.getySpriteScale()) + height * BLOCK_HEIGHT
									* Locator.getySpriteScale(), count));
							break;
						case "ia":
							count = Integer.valueOf(st.nextToken());
							coins.addAll(TrackDesign.addInverseArc(distance, (GROUND_HEIGHT * Locator.getySpriteScale()) + height * BLOCK_HEIGHT
									* Locator.getySpriteScale(), count));
							break;
						case "vl":
							count = Integer.valueOf(st.nextToken());
							coins.addAll(TrackDesign.addVerticalCoinLine(distance, (GROUND_HEIGHT * Locator.getySpriteScale()) + height * BLOCK_HEIGHT
									* Locator.getySpriteScale(), count));
							break;
						case "cr":
							count = Integer.valueOf(st.nextToken());
							int count2 = Integer.valueOf(st.nextToken());
							coins.addAll(TrackDesign.addCoinRectangle(distance, (GROUND_HEIGHT * Locator.getySpriteScale()) + height * BLOCK_HEIGHT
									* Locator.getySpriteScale(), count,count2));
							break;
						case "rha":
							count = Integer.valueOf(st.nextToken());
							coins.addAll(TrackDesign.addRightHalfArc(distance, (GROUND_HEIGHT * Locator.getySpriteScale()) + height * BLOCK_HEIGHT
									* Locator.getySpriteScale(), count));
							break;
						default:
							break;
						}
					}
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		}

	}

	/*
	 * private void readTrack() { String info = null; StringTokenizer st = null;
	 * while (lastDistance <= SCREEN_DISTANCE * Locator.getxSpriteScale() + 2 *
	 * BLOCK_WIDTH * Locator.getxSpriteScale() && !endOfFile) { try { info =
	 * br.readLine(); } catch (IOException e) { e.printStackTrace(); } if (info
	 * != null) { st = new StringTokenizer(info); if (st.hasMoreTokens()) {
	 * float totalDist = lastDistance + Integer.valueOf(st.nextToken()) *
	 * BLOCK_WIDTH * Locator.getxSpriteScale(); while (st.hasMoreTokens()) { //
	 * block y position int height = Integer.valueOf(st.nextToken()); // type of
	 * block switch (st.nextToken()) { case "n": blocks.add(new NormalBlock(new
	 * Vector2(totalDist, (GROUND_HEIGHT * Locator.getySpriteScale()) + height *
	 * BLOCK_HEIGHT Locator.getySpriteScale()))); break; case "e": goal = new
	 * Goal(new Vector2(totalDist, 0)); break; default: break; } } lastDistance
	 * = totalDist; } } else { endOfFile = true; } } }
	 */

}
